/**
* \file DGVAnimatedScan.cpp
*
* \brief This file defines the class for doing animated 1D plots using only Qt and QWT.
* \author Shekhar S. Chandra, 2008
*
* This file is part of DGV Library.
*
* DGV is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DGV is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DGV.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <QFileInfo>

#include <qwt_painter.h>
#include <qwt_plot_canvas.h>
#include <qwt_legend.h>
#include <qwt_plot_curve.h>
#include <qwt_scale_widget.h>

#include "DGVAnimatedScan.h"

DGVAnimatedScan::DGVAnimatedScan(QWidget *parent) :
    QwtPlot(parent),
    d_interval(0),
    d_timerId(-1)
{
    plotRow = 1;
    frameNo = 0;

    /// Disable polygon clipping
    QwtPainter::setDeviceClipping(false);

    /// We don't need the cache here
    canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
    canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);

#if QT_VERSION >= 0x040000
#ifdef Q_WS_X11
    /**
       Qt::WA_PaintOnScreen is only supported for X11, but leads
       to substantial bugs with Qt 4.2.x/Windows
     */
    canvas()->setAttribute(Qt::WA_PaintOnScreen, true);
#endif
#endif

    ///Set background
    const QColor bgColor(Qt::white);
    QPalette p = palette();
    p.setColor(backgroundRole(), bgColor);
    setPalette(p);

    alignScales();

    /// Assign a title
    //setTitle("Scan for " + FileName);
    insertLegend(new QwtLegend(), QwtPlot::BottomLegend);

    /// Insert new curves
    QwtPlotCurve *cRight = new QwtPlotCurve("Data");
    cRight->attach(this);

    /// Set curve styles
    cRight->setPen(QPen(Qt::red));

    /// Attach (don't copy) data. Both curves use the same x array.
    //firstIndex i;

    //xValues.resize(data.cols());
    //xValues = i;
    //yValues.resize(data.cols());

    /// \todo Possible crash here, data not set in animator
    //cRight->setRawData(xValues.data(), yValues.data(), scanData->cols());

#if 0
    ///  Insert zero line at y = 0
    QwtPlotMarker *mY = new QwtPlotMarker();
    mY->setLabelAlignment(Qt::AlignRight|Qt::AlignTop);
    mY->setLineStyle(QwtPlotMarker::HLine);
    mY->setYValue(0.0);
    mY->attach(this);
#endif

    /// Axis
    setAxisTitle(QwtPlot::xBottom, "Bin");
    setAxisAutoScale(QwtPlot::xBottom);

    setAxisTitle(QwtPlot::yLeft, "Values");
    setAxisAutoScale(QwtPlot::yLeft);

    setTimerInterval(0.0);
}

DGVAnimatedScan::DGVAnimatedScan(Array<imageType,2> &rowWiseData, QString scanName, QWidget *parent) :
    QwtPlot(parent),
    d_interval(0),
    d_timerId(-1)
{
    plotRow = 0;
    frameNo = 0;

    /// Disable polygon clipping
    QwtPainter::setDeviceClipping(false);

    /// We don't need the cache here
    canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
    canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);

#if QT_VERSION >= 0x040000
#ifdef Q_WS_X11
    /**
       Qt::WA_PaintOnScreen is only supported for X11, but leads
       to substantial bugs with Qt 4.2.x/Windows
     */
    canvas()->setAttribute(Qt::WA_PaintOnScreen, true);
#endif
#endif

    ///Set background
    const QColor bgColor(Qt::white);
    QPalette p = palette();
    p.setColor(backgroundRole(), bgColor);
    setPalette(p);

    alignScales();

    /// Assign a title
    name = scanName;
    setTitle(name);
    insertLegend(new QwtLegend(), QwtPlot::BottomLegend);

    /// Insert new curves
    QwtPlotCurve *cRight = new QwtPlotCurve("Data");
    cRight->attach(this);

    /// Set curve styles
    cRight->setPen(QPen(Qt::red));

    /// Attach (don't copy) data. Both curves use the same x array.
    firstIndex i;

    scanData = &rowWiseData;
    xValues.resize(scanData->cols());
    xValues = i;
    yValues.resize(scanData->cols());
    yValues = (*scanData)(0,Range::all());

    cRight->setRawData(xValues.data(), yValues.data(), scanData->cols());

#if 0
    ///  Insert zero line at y = 0
    QwtPlotMarker *mY = new QwtPlotMarker();
    mY->setLabelAlignment(Qt::AlignRight|Qt::AlignTop);
    mY->setLineStyle(QwtPlotMarker::HLine);
    mY->setYValue(0.0);
    mY->attach(this);
#endif

    /// Axis
    setAxisTitle(QwtPlot::xBottom, "Bin");
    setAxisAutoScale(QwtPlot::xBottom);

    setAxisTitle(QwtPlot::yLeft, "Values");
    setAxisAutoScale(QwtPlot::yLeft);

    setTimerInterval(0.0);
}

DGVAnimatedScan::~DGVAnimatedScan()
{
    //dtor
}

QString DGVAnimatedScan::strippedName()
{
    return QFileInfo(name).fileName();
}

QString DGVAnimatedScan::strippedNamePrefix()
{
    return "Scan: " + QFileInfo(name).fileName();
}

void DGVAnimatedScan::setTimerInterval(double ms)
{
    d_interval = qRound(ms);

    if ( d_timerId >= 0 )
    {
        killTimer(d_timerId);
        d_timerId = -1;
    }
    if (d_interval >= 0 )
        d_timerId = startTimer(d_interval);
}

void DGVAnimatedScan::saveFrame(QString filename)
{
    QPixmap frame;

    frame = QPixmap::grabWidget(this);

    frame.save(filename,0,100);
}

//  Generate new values
void DGVAnimatedScan::timerEvent(QTimerEvent *)
{
    //QString tmp;

    newValues();

    // update the display
    updateAxes();
    replot();

    /*if(saveAnimation && frameNo >= 0 && frameNo < data.rows())
    {
        saveFrame("ani" + tmp.setNum(frameNo) + ".png");
        frameNo ++;
    }*/
}

void DGVAnimatedScan::alignScales()
{
    /// The code below shows how to align the scales to
    /// the canvas frame, but is also a good example demonstrating
    /// why the spreaded API needs polishing.

    canvas()->setFrameStyle(QFrame::Box | QFrame::Plain );
    canvas()->setLineWidth(1);

    for ( int i = 0; i < QwtPlot::axisCnt; i++ )
    {
        QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(i);
        if ( scaleWidget )
            scaleWidget->setMargin(0);

        QwtScaleDraw *scaleDraw = (QwtScaleDraw *)axisScaleDraw(i);
        if ( scaleDraw )
            scaleDraw->enableComponent(QwtAbstractScaleDraw::Backbone, false);
    }
}

void setupCounter()
{
    /*QToolBar *toolBar = new QToolBar(this);
    toolBar->setFixedHeight(80);

#if QT_VERSION < 0x040000
    setDockEnabled(TornOff, true);
    setRightJustification(true);
#else
    toolBar->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
#endif
    QWidget *hBox = new QWidget(toolBar);
    QLabel *label = new QLabel("Timer Interval", hBox);
    QwtCounter *counter = new QwtCounter(hBox);
    counter->setRange(-1.0, 500.0, 1.0);

    QHBoxLayout *layout = new QHBoxLayout(hBox);
    layout->addWidget(label);
    layout->addWidget(counter);
    layout->addWidget(new QWidget(hBox), 10); // spacer);

#if QT_VERSION >= 0x040000
    toolBar->addWidget(hBox);
#endif
    addToolBar(toolBar);*/
}

void DGVAnimatedScan::newValues()
{
    yValues = (*scanData)(plotRow,Range::all());

    plotRow ++;
    plotRow = plotRow % scanData->rows();
}
